export function $(selector) {
  return document.querySelector(selector);
}
const components = ["VText", "RectShape", "CircleShape"];
export function isPreventDrop(component) {
  return !components.includes(component) && !component.startsWith("SVG");
}
export const getAssetsFile = (name: string) => {
  if (name) return new URL(`../assets/icon/${name}.png`, import.meta.url).href;
};
export const getItemVal = val => {
  let reg = /^-?\d+.?\d{1,3}/;
  if (val == 0 || val == "0") return 0;
  try {
    if (val && val.match) {
      let res = val.match(reg);
      if (res && res.length > 0) {
        res = res[0];
      } else {
        res = !isNaN(Number(val)) ? Number(val) : val;
      }
      if (res === "0.000") res = 0;
      return !isNaN(Number(res)) ? Number(res) : res;
    }
  } catch (error) {
    return !isNaN(Number(val)) ? Number(val) : val;
  }

  return !isNaN(Number(val)) ? Number(val) : val;
};
/**
 * 将可能是字符串的数值转换为 number／千分位字符串。
 *
 * 规则一：**数值归一化**
 * 1. **整数** - 原样返回
 * 2. **小数**
 *    - 小数位 ≤ 2 → 原样返回
 *    - 小数位  > 2 → 截断到 2 位（不四舍五入）
 *
 * 规则二：**大数格式化**
 * - 归一化后的绝对值 **≥ 1 000** →
 *   - 直接舍弃小数部分（取整数）
 *   - 按千分位分组展示，返回 **字符串**（如 `"12,345"`、`"-1,234"`）
 *
 * 其它：非法数值或非 string / number → 原样返回
 */
export const convertStringToNumber = <T>(value: T, LARGE_THRESHOLD = 1_000): T | number | string => {
  /** 步骤①：小数截断 / 整数直返 */
  const normalize = (num: number): number => {
    // 1) 整数
    if (Number.isInteger(num)) return num;

    // 2) 小数
    const [, frac = ""] = num.toString().split(".");
    return frac.length > 2 ? Math.trunc(num * 100) / 100 : num;
  };

  // -------- 处理输入为 string --------
  if (typeof value === "string" && value.trim() !== "") {
    const num = parseFloat(value.trim());
    if (Number.isNaN(num)) return value; // 非法数字 → 原样返回
    const normalized = normalize(num);

    // 步骤②：大数千分位
    if (Math.abs(normalized) >= LARGE_THRESHOLD) {
      return Math.trunc(normalized).toLocaleString(); // 舍弃小数并加分组
    }
    return normalized;
  }

  // -------- 处理输入为 number --------
  if (typeof value === "number" && !Number.isNaN(value)) {
    const normalized = normalize(value);
    if (Math.abs(normalized) >= LARGE_THRESHOLD) {
      return Math.trunc(normalized).toLocaleString();
    }
    return normalized;
  }

  // 其它类型或 NaN
  return value;
};

// export function formatTimestamp(timestamp: number | string, format: string = "YYYY-MM-DD HH:mm:ss") {
//   const date = new Date(timestamp);
//   const year = date.getFullYear();
//   const month = String(date.getMonth() + 1).padStart(2, "0");
//   const day = String(date.getDate()).padStart(2, "0");
//   const hours = String(date.getHours()).padStart(2, "0");
//   const minutes = String(date.getMinutes()).padStart(2, "0");
//   const seconds = String(date.getSeconds()).padStart(2, "0");

//   return format.replace("YYYY", year).replace("MM", month).replace("DD", day).replace("HH", hours).replace("mm", minutes).replace("ss", seconds);
// }
//根据指定key扁平化
export function flattenDataByKeys(data, keys) {
  const keyArray = keys.split(" ");

  function recursiveFlatten(obj, result = {}) {
    if (Array.isArray(obj)) {
      obj.forEach(item => recursiveFlatten(item, result));
    } else if (typeof obj === "object" && obj !== null) {
      let hasKey = keyArray.some(key => obj.hasOwnProperty(key));
      let resultKey = keyArray
        .map(key => obj[key])
        .filter(Boolean)
        .join("_");

      if (hasKey && resultKey) {
        result[resultKey] = obj;
      }

      for (let key in obj) {
        recursiveFlatten(obj[key], result);
      }
    }
    return result;
  }

  return recursiveFlatten(data);
}

export function isNotNumberOrShortBar(value) {
  if (value === "--") return false;
  return isNaN(Number(value));
}
export function normalizeNumber(value) {
  // 1. 检查值是否为数字，且不是 NaN
  if (typeof value === "number" && !isNaN(value)) {
    return value;
  }

  // 2. 如果值是字符串，尝试将其转换为数字
  if (typeof value === "string") {
    const parsedValue = parseFloat(value);

    // 3. 如果转换后的值是有效的数字
    if (!isNaN(parsedValue)) {
      return parsedValue;
    } else {
      // 4. 如果字符串无法转换为数字，打印错误并返回 0
      console.error("Invalid number format:", value);
      return 0;
    }
  }

  // 5. 处理其他类型（如 null, undefined 等），打印错误并返回 0
  console.error("Invalid type:", value);
  return 0;
}
/**
 * 将字符串数组统一补全 .png 后缀
 * @param target  原始字符串
 * @param ext     要检查 / 补全的扩展名 (默认 ".png")
 * @returns       新的字符串（保持纯函数，不修改原数组）
 */
export function ensurePngSuffix(target: string, ext: string = ".png"): string {
  return target.endsWith(ext) ? target : `${target}${ext}`;
}
/**
 * 从 localStorage 中读取数据，自动校验是否已过期
 * @param {string} key             - 读取的键名
 * @param {*} defaultValue = null  - 读取失败或已过期时返回的默认值
 * @returns {*}                     - 如果未过期返回存储值，否则删除并返回 defaultValue
 */
export function getWithExpiry(key, defaultValue = null) {
  const itemStr = localStorage.getItem(key);
  if (!itemStr) {
    return defaultValue;
  }
  try {
    const item = JSON.parse(itemStr);
    // 校验数据结构是否符合预期
    if (typeof item !== "object" || item === null || !("value" in item) || !("expiry" in item) || typeof item.expiry !== "number") {
      // 数据结构不符合预期，删除并返回默认值
      localStorage.removeItem(key);
      return defaultValue;
    }
    if (Date.now() > item.expiry) {
      localStorage.removeItem(key);
      return defaultValue;
    }
    return item.value;
  } catch (e) {
    // JSON 解析失败，删除并返回默认值
    localStorage.removeItem(key);
    return defaultValue;
  }
}

/**
 * 存储带过期时间的数据到 localStorage
 * @param {string} key - 存储的键名
 * @param {*} value - 要存储的值（可以是任意类型）
 * @param {number} ttl - 过期时间长度
 * @param {'h' | 'm'} unit - 时间单位，'h' 表示小时（默认），'m' 表示分钟
 */
export function setWithExpiry(key, value, ttl, unit = "h") {
  const now = Date.now();
  let ttlMs;

  if (unit === "m") {
    ttlMs = ttl * 60 * 1000;
  } else {
    ttlMs = ttl * 60 * 60 * 1000;
  }

  const item = {
    value,
    expiry: now + ttlMs
  };

  localStorage.setItem(key, JSON.stringify(item));
}
